package com.luke.exercise.concurrent;

import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class BlockingQueueDemo {
    
    public static void main(String[] args) {
        BlockingQueue<Task_1> buffer = new LinkedBlockingQueue<Task_1>(Constants_1.MAX_BUFFER_SIZE);
        ExecutorService es = Executors.newFixedThreadPool(5);
        for(int i = 1; i <= 2; ++i) {
            es.execute(new Producer_1(buffer));
        }
        for(int i = 1; i <= 3; ++i) {
            es.execute(new Consumer_1(buffer));
        }
    }
}

class Constants_1 {
    public static final int MAX_BUFFER_SIZE = 10;
}

class Task_1 {
    private String id;
    
    public Task_1() {
        id = UUID.randomUUID().toString();
    }
    
    public String toString() {
        return "Task_1[" + id + "]";
    }
}

class Consumer_1 implements Runnable {
    
    private BlockingQueue<Task_1> buffer;
    
    public Consumer_1(BlockingQueue<Task_1> buffer) {
        this.buffer = buffer;
    }

    public void run() {
        while(true) {
            try {
                Task_1 task = buffer.take();
                System.out.println("Consumer[" + Thread.currentThread().getName()+"] consume "+ task);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Producer_1 implements Runnable {

    private BlockingQueue<Task_1> buffer;
    
    public Producer_1(BlockingQueue<Task_1> buffer) {
        this.buffer = buffer;
    }
    public void run() {
        while(true) {
            Task_1 task = new Task_1();
            try {
                buffer.put(task);
                System.out.println("[Producer" + Thread.currentThread().getName()+ "] produce " + task);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
}